#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>

//#include <asm/termios.h>

#include "nstar_m26_api.h"

/*for 96c*/

#define M26_VTIME 		 1u 		/*单位:100ms*/

#define M26_DEFAULT_USART_BOUND 115200 
#define M26_DEFAULT_START_STEP	1		/*默认已开机*/
#define M26_DEFAULT_LOOP_GAP   	10u 	/*默认服务轮询间隔，200ms*/
#define M26_REC_DBG			   	0

static int fd_m26com= 0;
static int m26_set_termios(int fd,long speed,char databit,char stopbit,char oebit,unsigned char vttime);

int nstar_at_hadware_init(void);


void plat_gpio_gsm_on(void) {

}

void plat_gpio_gsm_off(void) {

}

char* plat_gsm_usart_get(void) {
    return "/dev/ttyNstar7";
}

void fun_m26_pwctl(void)
{
	//M26模块开机(使能PWRON_Pin)，注意：
	//1.电路设计时候需要：控制端IO口默认低电平，且下拉
	//2.推荐开集电路，此时控制端只需给一个>800ms高电平脉冲即可开机/关机
    plat_gpio_gsm_on();
    usleep(1000*1000);
    plat_gpio_gsm_off();
}

void fun_m26_send(const unsigned char *tbuf, unsigned int len)
{
	int fd= fd_m26com;
	int ret = write(fd, tbuf, len);
    if(ret < 0) {
        ;
    }
}

/*blocking rec*/
unsigned int fun_m26_rec(unsigned char *rbuf)
{
	unsigned int len, rlen; 
	int fd= fd_m26com;
	rlen = read(fd, rbuf, M26_MAX_RLEN);	
	if(rlen > 0)	
	{
		do{
			len= read(fd, &rbuf[rlen], M26_MAX_RLEN- rlen);
			if(len>0)
				rlen+=len;
		}while(len > 0 && rlen < M26_MAX_RLEN);
		rbuf[rlen]= 0;	//添加结束符
		if(M26_REC_DBG)
			printf("m26 ack: %s", rbuf);		
		return rlen;
	}
	return 0;
}


void nstar_at_hadware_close(void)
{
	if(fd_m26com > 0){
		if(0 != close(fd_m26com))
			printf("at com close err\n");
	}
	fd_m26com= 0;
}

int nstar_at_hadware_init(void)
{
	int fd,ret;
	int bound=M26_DEFAULT_USART_BOUND;

	if(fd_m26com > 0)
		close(fd_m26com);
	fd = open(plat_gsm_usart_get(), O_RDWR | O_NOCTTY);
	if(fd < 0) {
		perror("open err\n");
		return -1;
	}	
	ret = m26_set_termios(fd,bound,8,'1','N', M26_VTIME);	
	
	if(ret < 0) {
		perror("set uart arrt faile \n");
		return -2;
	}	
	fd_m26com= fd;
	printf("init ok %d\n", fd_m26com);
	return 0;
}



void nstar_at_servo(void *parm)
{
	M26_servo((void*)M26_DEFAULT_START_STEP, M26_DEFAULT_LOOP_GAP);	
}


void ec20_set_termios(void)
{
	int ret,fd;
	fd= fd_m26com;
	int bound=M26_DEFAULT_USART_BOUND;
	ret = m26_set_termios(fd,bound,8,'1','N', 0u);	
	if(ret < 0) {
		perror("set uart arrt faile \n");
	}
}

static int m26_set_termios(int fd,long speed,char databit,char stopbit,char oebit, unsigned char vttime)
{  

	struct termios tty;
	struct termios *pstTtyattr= &tty;
	int err = -1;  
	memset(pstTtyattr, 0 , sizeof(struct termios));
	pstTtyattr->c_cflag |= CLOCAL | CREAD;  
	pstTtyattr->c_cflag &= ~CSIZE;  
	switch(databit)    
	{  
		case 7:	  
			pstTtyattr->c_cflag |= CS7;	  
			break;  
		case 8:	  
			pstTtyattr->c_cflag |= CS8;	  
		  break;  
		default:	  
			pstTtyattr->c_cflag |= CS8;	  
			break;    
	}  
	switch(stopbit)    
	{		
		case 1:			
			pstTtyattr->c_cflag &= ~CSTOPB;			
			break;		
		case 2:			
			pstTtyattr->c_cflag |= CSTOPB;		  
			break;		
		default:		  
			pstTtyattr->c_cflag &= ~CSTOPB;		  
			break;    
	}  
	switch(oebit)    
	{  
		case 'O':
			//odd	 
			pstTtyattr->c_cflag |= PARENB;	  
			pstTtyattr->c_cflag |= (INPCK | ISTRIP);	  
			pstTtyattr->c_cflag |= PARODD;	  
			break;  
		case 'E'://even	 
			pstTtyattr->c_cflag |= PARENB;	  
			pstTtyattr->c_cflag |= (INPCK | ISTRIP);	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;  
		case 'N':	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;  
		default:	  
			pstTtyattr->c_cflag &= ~PARODD;	  
			break;    
	}  
	switch(speed)    
	{  
		case 2400:	  
			cfsetispeed(pstTtyattr,B2400);	  
			cfsetospeed(pstTtyattr,B2400);	  
			break;  
		case 4800:	  
			cfsetispeed(pstTtyattr,B4800);	  
			cfsetospeed(pstTtyattr,B4800);	  
			break;  
		case 9600:	  
			cfsetispeed(pstTtyattr,B9600);	  
			cfsetospeed(pstTtyattr,B9600);	  
			break;  
		case 57600:	  
			cfsetispeed(pstTtyattr,B57600);	  
			cfsetospeed(pstTtyattr,B57600);	  
			break;  
		case 19200:	  
			cfsetispeed(pstTtyattr,B19200);	  
			cfsetospeed(pstTtyattr,B19200);	  
			break;  
		case 115200://	 
		//	cfsetspeed(pstTtyattr,B115200);	  
			cfsetispeed(pstTtyattr,B115200);	  
			cfsetospeed(pstTtyattr,B115200);	  
			break;  
		default:	  
			cfsetispeed(pstTtyattr,B9600);	  
			cfsetospeed(pstTtyattr,B9600);	  
			break;    
	}  
	pstTtyattr->c_cc[VTIME] = vttime;  
	pstTtyattr->c_cc[VMIN] = 0;  
	if(tcflush(fd,TCIFLUSH)!= 0)
	{
		perror("tcgetattr");
		return err;
	}
	if((tcsetattr(fd,TCSANOW,pstTtyattr)) != 0)   /*激活新配置*/ 
	{  	
		perror("popen");
	}  
	else  
	{	   
		err = 0;  
	}  
	return err;
}


